package com.bmps.springcloud.insuredmicroservice.service.calculate;

import com.bmps.springcloud.common.response.TaskResponseModel;
import com.bmps.springcloud.common.task.TaskExecutor;
import com.bmps.springcloud.insuredmicroservice.callback.calculate.CalculateAccountValueCallBack;
import com.bmps.springcloud.insuredmicroservice.config.accept.ProductConfig;
import com.bmps.springcloud.insuredmicroservice.constant.accept.AcceptConstant;
import com.bmps.springcloud.insuredmicroservice.constant.accept.StrategyConstant;
import com.bmps.springcloud.insuredmicroservice.model.accept.LcPolModel;
import com.bmps.springcloud.insuredmicroservice.model.accept.resquest.ProductInfoModel;
import com.bmps.springcloud.insuredmicroservice.model.accept.resquest.ProductModel;
import com.bmps.springcloud.insuredmicroservice.repository.calculate.coresystem.AccountValueRepository;
import com.bmps.springcloud.insuredmicroservice.service.RedisService;
import com.bmps.springcloud.insuredmicroservice.service.underwrite.strategy.minordeath.riskstrategy.RiskStrategy;
import com.bmps.springcloud.insuredmicroservice.service.underwrite.strategy.minordeath.riskstrategy.RiskStrategyFactory;
import com.bmps.springcloud.insuredmicroservice.util.accept.AcceptUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * description:
 *
 * @author jackdaw
 * @date 2019-12-25 16:57
 */
@Service
public class DeathLiabilityInsuranceServiceImpl implements DeathLiabilityInsuranceService {
    private Logger logger = LoggerFactory.getLogger(DeathLiabilityInsuranceServiceImpl.class);
    private final TaskExecutor taskExecutor;
    private final ProductConfig productConfig;
    private final AccountValueInsuranceService accountValueInsuranceService;
    private final AccountValueRepository accountValueRepository;
    private final RedisService redisService;

    public DeathLiabilityInsuranceServiceImpl(TaskExecutor taskExecutor, ProductConfig productConfig, AccountValueInsuranceService accountValueInsuranceService, AccountValueRepository accountValueRepository, RedisService redisService) {
        this.taskExecutor = taskExecutor;
        this.productConfig = productConfig;
        this.accountValueInsuranceService = accountValueInsuranceService;
        this.accountValueRepository = accountValueRepository;
        this.redisService = redisService;
    }

    @Override
    public BigDecimal historyDeathLiabilityAmnt(List<LcPolModel> lcPolModels) {
        BigDecimal total = BigDecimal.valueOf(0);
        //获取需要查询账户价值的险种
        List<Callable<TaskResponseModel>> baseTaskCallbackList = new ArrayList<>();
        for (LcPolModel lcPolModel : lcPolModels) {
            if (productConfig.getAccountValueList().contains(lcPolModel.getRiskCode())) {
                Callable<TaskResponseModel> insuredCallBack = new CalculateAccountValueCallBack(lcPolModel.getPolNo(), lcPolModel, accountValueInsuranceService);
                baseTaskCallbackList.add(insuredCallBack);
            }
        }
        if (CollectionUtils.isNotEmpty(baseTaskCallbackList)) {
            List<TaskResponseModel> taskResponseModelList = taskExecutor.execute(baseTaskCallbackList);
            //获取任务中的累积保额
            lcPolModels = this.getAmountByRiskCode(taskResponseModelList, lcPolModels);
        }
        for (LcPolModel lcPolModel : lcPolModels) {
            String riskCode = lcPolModel.getRiskCode();
            RiskStrategy strategy = RiskStrategyFactory.getInsuranceStrategy(riskCode);
            if (strategy == null) {
                if (StringUtils.equals(riskCode, StrategyConstant.AAT064) || StringUtils.equals(riskCode, StrategyConstant.HCT007)) {
                    continue;
                }
                total = total.add(lcPolModel.getAmnt());
            } else {
                BigDecimal amount = strategy.getAmount(lcPolModel, lcPolModels, false);
                total = total.add(amount);
            }
        }
        return total;
    }

    @Override
    public BigDecimal currentDeathLiabilityAmnt(int prodInsSeq, int age, ProductInfoModel productInfoModel) {
        if (age >= StrategyConstant.ADULT_AGE) {
            return BigDecimal.valueOf(0);
        }
        BigDecimal total = BigDecimal.valueOf(0);
        List<ProductModel> productModels = productInfoModel.getProducts().getProduct();
        int payIntv = Integer.parseInt(productInfoModel.getPayIntv());
        List<String> riskList = productConfig.getAccumulatedRiskList();
        List<LcPolModel> lcPolModels = new ArrayList<>(productModels.size());
        for (ProductModel productModel : productModels) {
            if (prodInsSeq == productModel.getProdInsSeq()) {
                lcPolModels.add(createLcPolModel(age, payIntv, productModel));
            }
        }
        for (LcPolModel model : lcPolModels) {
            for (String riskString : riskList) {
                if (riskString.contains(model.getRiskCode())) {
                    if (AcceptUtil.isRiskType(StrategyConstant.DEATH_LIABILITY_INSURANCE, Integer.parseInt(riskString.split(":")[1]))) {
                        String riskCode = model.getRiskCode();
                        RiskStrategy strategy = RiskStrategyFactory.getInsuranceStrategy(riskCode);
                        if (strategy == null) {
                            total = total.add(model.getAmnt());
                        } else {
                            BigDecimal amount = strategy.getAmount(model, lcPolModels, true);
                            total = total.add(amount);
                        }
                    }
                    continue;
                }
            }
        }
        return total;
    }

    @Override
    public List<LcPolModel> queryHistoryPolicy(String prtNo, String insuredNo) {
        return accountValueRepository.queryHistoryPolicy(prtNo, insuredNo);
    }

    private List<LcPolModel> getAccountValueRisk(List<LcPolModel> lcPolModels) {
        List<LcPolModel> list = new ArrayList<>(lcPolModels.size());
        for (LcPolModel lcPolModel : lcPolModels) {
            if (productConfig.getAccountValueList().contains(lcPolModel.getRiskCode())) {
                list.add(lcPolModel);
            }
        }
        return list;
    }

    private List<LcPolModel> getAmountByRiskCode(List<TaskResponseModel> taskResponseModelList, List<LcPolModel> lcPolModels) {

        for (TaskResponseModel taskResponseModel : taskResponseModelList) {
            for (LcPolModel lcPolModel : lcPolModels) {
                if (StringUtils.equals(lcPolModel.getPolNo(), taskResponseModel.getKey())) {
                    lcPolModel.setAccountValue(taskResponseModel.getBigDecimal());
                }
            }
        }

        return new ArrayList<>(lcPolModels);
    }

    private double getNormalAmountByRiskCode(List<LcPolModel> lcPolModels) {
        double total = 0;
//        //特殊险种处理
//        this.dealSpecialRisk(lcPolModels);
//        for (LcPolModel lcPolModel : lcPolModels) {
//            String riskCode = lcPolModel.getRiskCode();
//            if (StringUtils.equals(riskCode, StrategyConstant.LBT023)) {
//                total += lcPolModel.getPrem() * 0.2;
//            } else if (StringUtils.equals(riskCode, StrategyConstant.LBT026) || StringUtils.equals(riskCode, StrategyConstant.AAT064)) {
//                double yearPrem = lcPolModel.getSumPrem();
//                if (lcPolModel.getPayIntv() == 1) {
//                    yearPrem = yearPrem * 12;
//                }
//                if (18 - lcPolModel.getInsuredAppAge() <= 0) {
//                    total += lcPolModel.getAmnt();
//                } else {
//                    if (18 - lcPolModel.getInsuredAppAge() < lcPolModel.getPayYears()) {
//                        total += lcPolModel.getAmnt() * 3 + (yearPrem * 0.6 * (18 - lcPolModel.getInsuredAppAge()));
//                    } else {
//                        total += lcPolModel.getAmnt() * 3 + (yearPrem * 0.6 * lcPolModel.getPayYears());
//                    }
//                }
//            } else if (StringUtils.equals(riskCode, StrategyConstant.LBT028)) {
//                //年交保费
//                double yearPrem = getYearPrem(lcPolModel.getPayIntv(), lcPolModel.getSumPrem());
//                //判断年龄如果是保全复效则需要重新计算被保险人年龄
//                int tAppAge = lcPolModel.getInsuredAppAge();
//                if (lcPolModel.getPayIntv() == 0) {
//                    total += yearPrem * 1;
//                } else if (18 - tAppAge >= lcPolModel.getPayYears()) {
//                    //如果（18-被保险人的投保年龄）大于等于缴费期，则未成年人的身故保额设置为年交保费*缴费期*1
//                    total += yearPrem * lcPolModel.getPayYears() * 1;
//                } else if (18 - tAppAge < lcPolModel.getPayYears() && 18 - tAppAge > 0) {
//                    //如果（18-被保险人的投保年龄）小于缴费期并且大于0，则未成年人的身故保额设置为年交保费*（18-被保险人的投保年龄）*1
//                    total = yearPrem * (18 - tAppAge) * 1;
//                } else {
//                    //如果（18-被保险人的投保年龄）小于等于0，则未成年人的身故保额设置为0。
//                    total += 0;
//                }
//            } else if (StringUtils.equals(riskCode, StrategyConstant.HCT010)) {
//                double yearPrem = getYearPrem(lcPolModel.getPayIntv(), lcPolModel.getPrem());
//                //判断年龄如果是保全复效则需要重新计算被保险人年龄
//                int tAppAge = lcPolModel.getInsuredAppAge();
//                if (18 - tAppAge >= lcPolModel.getPayYears()) {
//                    //如果（18-被保险人的投保年龄）大于等于缴费期，则未成年人的身故保额设置为年交保费*缴费期*1
//                    total += yearPrem * lcPolModel.getPayYears() * 1;
//                } else if (18 - tAppAge < lcPolModel.getPayYears() && 18 - tAppAge > 0) {
//                    //如果（18-被保险人的投保年龄）小于缴费期并且大于0，则未成年人的身故保额设置为年交保费*（18-被保险人的投保年龄）*1
//                    total += yearPrem * (18 - tAppAge) * 1;
//                } else {
//                    //如果（18-被保险人的投保年龄）小于等于0，则未成年人的身故保额设置为0。
//                    total += 0;
//                }
//
//            } else if (StringUtils.equals(riskCode, StrategyConstant.LBT030)) {
//
//                //判断年龄如果是保全复效则需要重新计算被保险人年龄
//                int tAppAge = lcPolModel.getInsuredAppAge();
//
//                //获取主险信息
//                LcPolModel mainPol = accountValueRepository.queryMainPol(lcPolModel.getPrtNo());
//
//                if (18 - tAppAge >= lcPolModel.getPayYears()) {
//                    //如果（18-被保险人的投保年龄）大于等于缴费期，则未成年人的身故保额设置为（主险保费*缴费期，险种保费的60%*缴费期）比较取较大值
//                    if (mainPol.getPrem() * lcPolModel.getPayYears() - 0.6 * lcPolModel.getPrem() * lcPolModel.getPayYears() > 0) {
//                        total += mainPol.getPrem() * lcPolModel.getPayYears();
//                    } else {
//                        total += 0.6 * lcPolModel.getPrem() * lcPolModel.getPayYears();
//                    }
//                } else if (18 - tAppAge < lcPolModel.getPayYears() && 18 - tAppAge > 0) {
//                    //如果（18-被保险人的投保年龄）小于缴费期并且大于0，则未成年人的身故保额设置为（主险保费*（18-被保险人的投保年龄），险种保费的60%*（18-被保险人的投保年龄））比较取较大值；
//                    if (mainPol.getPrem() * (18 - tAppAge) - 0.6 * lcPolModel.getPrem() * (18 - tAppAge) > 0) {
//                        total += mainPol.getPrem() * (18 - tAppAge);
//                    } else {
//                        total += 0.6 * lcPolModel.getPrem() * (18 - tAppAge);
//                    }
//                } else {
//                    //如果（18-被保险人的投保年龄）小于等于0，则未成年人的身故保额设置为0。
//                    total += 0;
//                }
//
//            } else if (StringUtils.equals(riskCode, StrategyConstant.LBT031)) {
//                double yearPrem = getYearPrem(lcPolModel.getPayIntv(), lcPolModel.getPrem());
//                LcPolModel mainPol = accountValueRepository.queryMainPol(lcPolModel.getPrtNo());
//                double mainYearPrem = getYearPrem(mainPol.getPayIntv(), mainPol.getPrem());
//                //判断年龄如果是保全复效则需要重新计算被保险人年龄
//                int tAppAge = lcPolModel.getInsuredAppAge();
//                if (18 - tAppAge >= lcPolModel.getPayYears()) {
//                    //如果（18-被保险人的投保年龄）大于等于缴费期，则未成年人的身故保额设置为主险保费+附加两全保险的保费之和）*20%*缴费期
//                    total += yearPrem * 0.2 * (lcPolModel.getPayIntv() == 0 ? 1 : lcPolModel.getPayYears()) + mainYearPrem * 0.2 * (mainPol.getPayIntv() == 0 ? 1 : lcPolModel.getPayYears());
//                } else if (18 - tAppAge < lcPolModel.getPayYears() && 18 - tAppAge > 0) {
//                    //如果（18-被保险人的投保年龄）小于缴费期并且大于0，则未成年人的身故保额设置为主险保费+附加两全保险的保费之和）*20%*（18-被保险人的投保年龄）
//                    total += yearPrem * 0.2 * (lcPolModel.getPayIntv() == 0 ? 1 : (18 - tAppAge)) + mainYearPrem * 0.2 * (mainPol.getPayIntv() == 0 ? 1 : (18 - tAppAge));
//                } else {
//                    //如果（18-被保险人的投保年龄）小于等于0，则未成年人的身故保额设置为0。
//                    total += 0;
//                }
//
//
//            } else if (StringUtils.equals(riskCode, StrategyConstant.LBP025) || StringUtils.equals(riskCode, StrategyConstant.LBP026)) {
//                total += lcPolModel.getPrem() * 0.2;
//            } else if (StringUtils.equals(riskCode, StrategyConstant.AAT070) || StringUtils.equals(riskCode, StrategyConstant.AAT072)) {
//                if (lcPolModel.getInsuredAppAge() < 18) {
//                    total += lcPolModel.getAmnt() * 3;
//                }
//            } else if (StringUtils.equals(riskCode, StrategyConstant.LBT034)) {
//                double yearPrem = getYearPrem(lcPolModel.getPayIntv(), lcPolModel.getPrem());
//                LcPolModel mainPol = accountValueRepository.queryMainPol(lcPolModel.getPrtNo());
//                int tAppAge = lcPolModel.getInsuredAppAge();
//                double mainYearPrem = getYearPrem(mainPol.getPayIntv(), mainPol.getPrem());
//                if (18 - tAppAge >= lcPolModel.getPayYears()) {
//                    //如果（18-被保险人的投保年龄）大于等于缴费期，则未成年人的身故保额设置为（主险保费*缴费期，险种保费的60%*缴费期）比较取较大值
//                    if (mainYearPrem * mainPol.getPayYears() - 0.6 * yearPrem * lcPolModel.getPayYears() > 0) {
//                        total += mainYearPrem * mainPol.getPayYears();
//                    } else {
//                        total += 0.6 * yearPrem * lcPolModel.getPayYears();
//                    }
//                } else if (18 - tAppAge < lcPolModel.getPayYears() && 18 - tAppAge > 0) {
//                    //如果（18-被保险人的投保年龄）小于缴费期并且大于0，则未成年人的身故保额设置为（主险保费*（18-被保险人的投保年龄），险种保费的60%*（18-被保险人的投保年龄））比较取较大值；
//                    if (mainYearPrem * (18 - tAppAge) - 0.6 * yearPrem * (18 - tAppAge) > 0) {
//                        total += mainYearPrem * (18 - tAppAge);
//                    } else {
//                        total += 0.6 * yearPrem * (18 - tAppAge);
//                    }
//                } else {
//                    //如果（18-被保险人的投保年龄）小于等于0，则未成年人的身故保额设置为0。
//                    total += 0;
//                }
//            } else {
//                total += lcPolModel.getAmnt();
//            }
//        }

        return total;
    }

    public void dealSpecialRisk(List<LcPolModel> polEntities) {
        String prtNo;
        for (LcPolModel lcPolModel : polEntities) {
            if (StringUtils.equals(lcPolModel.getRiskCode(), "LBT026")) {
                prtNo = lcPolModel.getPrtNo();
                for (LcPolModel polEntity : polEntities) {
                    if (StringUtils.equals(polEntity.getRiskCode(), "AAT064") && StringUtils.equals(prtNo, polEntity.getPrtNo())) {
                        lcPolModel.setSumPrem(lcPolModel.getPrem().add(polEntity.getPrem()));
                    }
                }
            }
            if (StringUtils.equals(lcPolModel.getRiskCode(), "LBT028")) {
                prtNo = lcPolModel.getPrtNo();
                for (LcPolModel polEntity : polEntities) {
                    if (StringUtils.equals(polEntity.getRiskCode(), "HCT007") && StringUtils.equals(prtNo, polEntity.getPrtNo())) {
                        lcPolModel.setSumPrem(lcPolModel.getPrem().add(polEntity.getPrem()));
                    }
                }
            }
        }

    }


    /**
     * 包装lcPolModel
     *
     * @param age          年龄
     * @param payIntv      交费频次
     * @param productModel 产品对象
     * @return lcPolModel
     */
    private LcPolModel createLcPolModel(int age, int payIntv, ProductModel productModel) {

        LcPolModel lcPolModel = new LcPolModel();
        lcPolModel.setPayIntv(payIntv);
        lcPolModel.setInsuredAppAge(age);
        lcPolModel.setRiskCode(productModel.getProdCode());
        lcPolModel.setPrem(productModel.getPrem());
        lcPolModel.setAmnt(productModel.getAmnt());
        if (StringUtils.equals(StrategyConstant.YEAR, productModel.getPayYearFlag())) {
            lcPolModel.setPayYears(productModel.getPayYear());
        } else if (StringUtils.equals(StrategyConstant.AGE, productModel.getPayYearFlag())) {
            lcPolModel.setPayYears(productModel.getPayYear() - age);
        }

        return lcPolModel;
    }

}

